<template>
  <transition name="fade"
    ><div v-bind="$attrs" ref="infoCard" class="info-card" v-if="modelValue">
      <user-info :user-data="userData" @open-modal="openModal"></user-info>
      <div v-if="slots.footer" class="info-card__footer">
        <slot name="footer"></slot>
      </div></div
  ></transition>
  <Modal v-model="showModal">
    <img class="img-browser" :src="imgSrc" alt="" />
  </Modal>
</template>

<script lang="ts">
export default defineComponent({
  inheritAttrs: false,
});
</script>

<script lang="ts" setup>
import { ref, watch, nextTick, useSlots, defineComponent } from "vue";
import userInfo from "./userInfo.vue";
import Modal from "@/components/ui-components/modal.vue";

const props = defineProps<{
  // 是否显示该组件
  modelValue: boolean;
  // 触发该组件显示的元素
  triggerEle: HTMLElement;
  userData: User;
}>();

const emits = defineEmits<{
  (e: "update:modelValue", show: boolean): void;
}>();

const slots = useSlots();

/**
 * 给该组件一个ref属性
 */
const infoCard = ref<HTMLDivElement>(document.createElement("div"));

/**
 * 判断用户所点击的元素是否符合标准
 */
const judgeClick = (e: Event) => {
  if (props.triggerEle && infoCard.value) {
    const target: HTMLElement = e.target as HTMLElement;
    if (!props.triggerEle.contains(target) && !infoCard.value.contains(target))
      emits("update:modelValue", false);
  }
};

/**
 * 更新该组件的位置
 */
const updateDirection = () => {
  if (infoCard.value) {
    let bodyWid: number = document.body.scrollWidth;
    // 如果出现滚动条此时可能设置了body的padding-right来防止页面抖动
    const bodyPaddRight: number = +document.body.style.paddingRight.replace("px", "");
    if (bodyPaddRight) bodyWid -= bodyPaddRight;

    const parentNode: HTMLElement = infoCard.value.parentNode as any;
    const parentNodeWid: number = parentNode.offsetWidth;
    const selfWid: number = infoCard.value.offsetWidth;
    const selfHei: number = infoCard.value.offsetHeight;
    const rect = parentNode.getBoundingClientRect();
    if (bodyWid - rect.x - parentNodeWid - scrollX - 6 < selfWid)
      infoCard.value.style.cssText += "left: -6px;transform: translateX(-100%)";
    else {
      infoCard.value.style.left = "";
      infoCard.value.style.transform = "";
    }

    if (rect.y < selfHei) {
      infoCard.value.style.top = "0";
    } else infoCard.value.style.bottom = "0";
  }
};

watch(
  () => props.modelValue,
  (show: boolean) => {
    if (show) {
      document.addEventListener("click", judgeClick);
      window.addEventListener("resize", updateDirection);
      nextTick(() => {
        updateDirection();
      });
    } else {
      document.removeEventListener("click", judgeClick);
      window.removeEventListener("resize", updateDirection);
    }
  }
);

/**
 * 当前用户查看的图片的url
 */
const imgSrc = ref<string>("");
/**
 * 是否显示模态框
 */
const showModal = ref<boolean>(false);
// 浏览图片时打开模态框
const openModal: (url: string) => void = (url: string): void => {
  imgSrc.value = url;
  showModal.value = true;
};
</script>

<style lang="scss" scoped>
.fade {
  @include fade(0.15s, ease);
}

.info-card {
  width: 260px;
  position: absolute;
  left: calc(100% + 6px);
  z-index: 99;
  padding: 15px 15px 25px;
  border-radius: 3px;
  background-color: #fff;
  box-shadow: 0px 12px 32px 4px rgba(0, 0, 0, 0.04), 0px 8px 20px rgba(0, 0, 0, 0.08);
  box-sizing: border-box;

  &__footer {
    text-align: center;
    margin-top: 15px;
  }
}
</style>
